import { HttpAxios } from "./axios";
import type {
  AxiosResponse,
  InternalAxiosRequestConfig,
  AxiosInstance,
} from "axios";
import { ResultEnum } from "@/config";
import { getToken, isString } from "@/utils";
import { RequestEnum, ContentTypeEnum } from "@/config";
import qs from "qs";
import AxiosCancel from "./axiosCancel";
import { useMessage, useLoginOut } from "@/hooks";
import {
  MessageTypeEnum,
  MessageEnum,
  ErrorEnum,
  ErrMsgnum,
} from "@/config/enums";
import axios from "axios";

let { createMessage } = useMessage();

function messageHandle(
  options: AxionsOptions.RequestOptions,
  type: MessageEnum,
  message: string | undefined
) {
  if (!message || !options.messageMode || !options.messageBoxMode) return;

  switch (options.messageMode) {
    case MessageTypeEnum.MESSAGE:
      createMessage(
        options.messageMode,
        type
      )({
        options: {
          message,
        },
      });
      break;
    case MessageTypeEnum.MESSAGEBOX:
      createMessage(
        options.messageMode,
        options.messageBoxMode
      )({
        message,
        title: options.messageBoxTitle,
        options:{
          type
        }
      });
      break;
  }
}

//创建请求模块
export function createAxios() {

  //拦截器对象
  const axiosInterceptors: AxionsOptions.AxiosInterceptors = {
    
    //请求拦截器
    requestInterceptor(
      config: InternalAxiosRequestConfig & AxionsOptions.RequestOptions,
    ) {

      let cfg = Object.assign({}, config);

      //判断是否开启取消重复请求
      if (!cfg.ignoreCancelToken) {
        AxiosCancel.addPending(cfg);
      }

      //token
      const token = getToken();
      if (token && cfg.token) {
        cfg.headers.Authorization = cfg.authenticationScheme
          ? `${cfg.authenticationScheme} ${token}`
          : token;
      }

      //拼接url
      if (cfg.apiPrefixUrl) {
        cfg.url = `${cfg.apiPrefixUrl}${cfg.url}`;
        Reflect.deleteProperty(cfg,'apiPrefixUrl')
      }

      //如果是非get接口且需要用parmas传参
      if (cfg.method?.toUpperCase() !== RequestEnum.GET) {
        if (
          cfg.postBodyToUrl &&
          Reflect.has(cfg, "data") &&
          !Reflect.has(cfg, "params")
        ) {
          cfg.params = cfg.data;
          cfg.data = undefined;
        }
      }

      //兼容restful模式
      if (cfg.restful && isString(cfg.params)) {
        cfg.url = `${cfg.url}${cfg.params}`;
        cfg.params = undefined;
      }


      if (
        cfg.headers["Content-Type"] === ContentTypeEnum.FORM_URLENCODED &&
        Reflect.has(cfg, "data") &&
        cfg.url !== RequestEnum.GET
      ) {
        cfg.data = qs.stringify(cfg.data, {
          arrayFormat: "brackets",
        });
      }
      return cfg;
    },

    //返回拦截器
    responseInterceptor(res: AxiosResponse<Result>) {

      res && AxiosCancel.removePending(AxiosCancel.getPendingUrl(res.config));

      let data = res.data;
      let config = res.config as AxionsOptions.RequestConfig;

      //下面逻辑按照项目自己来设计
      let { code, message } = data || {};
      let msg;

      switch (code) {
        case ResultEnum.SUCCESS:
          msg = message || config.successMessage;
          if (config.showSuccessMessage) {
            messageHandle(config, MessageEnum.SUCCESS, msg);
          }
          break;
        case ResultEnum.NOLOGIN:
          msg = message || config.noLoginMessage;
          if (config.showSuccessMessage) {
            messageHandle(config, MessageEnum.WARINING, msg);
          }
          let { useLogoutHandle } = useLoginOut();
          useLogoutHandle();
          break;
        default:
          msg = message || config.warningMessage;
          if (config.showSuccessMessage) {
            messageHandle(config, MessageEnum.WARINING, msg);
          }
          break;
      }

      return Promise.resolve(res.data);
    },

    //错误拦截器
    responseErrorInterceptor(instance: AxiosInstance, error: any) {

      const { response, code, message, config } = error;
      const err: string = error?.toString?.() ?? "";
      let errMessage = "";

      if (axios.isCancel(error)) {
        return Promise.reject(error);
      }

      //超时或网络异常
      try {
        if (code === "ECONNABORTED" && message.indexOf("timeout") !== -1) {
          errMessage = ErrMsgnum.ERROR_ECONNABORTED_MESSAGE;
        }
        if (err?.includes("Network Error")) {
          errMessage = ErrMsgnum.ERROR_Network_MESSAGE;
        }
        if (errMessage) {
          if (config?.showErrorMessage) {
            messageHandle(config, MessageEnum.ERROR, errMessage);
          }
          return Promise.reject(error);
        }
      } catch (error) {
        throw new Error(error as unknown as string);
      }

      //根据项目自己修改
      const msg: string = response?.data?.error?.message || "";
      switch (response?.status) {
        case ErrorEnum.ERROR401:
          errMessage = ErrMsgnum.ERROR401_MESSAGE;
          let { useLogoutHandle } = useLoginOut();
          useLogoutHandle();
          break;
        case ErrorEnum.ERROR500:
          errMessage = ErrMsgnum.ERROR500_MESSAGE;
          break;
        case ErrorEnum.ERROR502:
          errMessage = ErrMsgnum.ERROR502_MESSAGE;
          break;
        default:
          errMessage = msg;
          break;
      }
      messageHandle(config, MessageEnum.ERROR, errMessage);
      return Promise.reject(error);
    },
  };

  //执行HttpAxios工厂函数（传入系统默认请求config、拦截器对象等），并返回实例
  return HttpAxios.factory({
    authenticationScheme: "",
    interceptors: axiosInterceptors,
  });
}

//导出时执行 createAxios
export const httpAxios = createAxios();
